package com.ruoyi.system.service.impl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.constant.YouDaoKEY;
import com.ruoyi.stu.mapper.StuStudentWordMapper;
import com.ruoyi.system.domain.SysCourse;
import com.ruoyi.system.domain.SysTextbook;
import com.ruoyi.system.domain.SysUnit;
import com.ruoyi.system.domain.SysUnitWord;
import com.ruoyi.system.domain.SysWord;
import com.ruoyi.system.mapper.SysCourseMapper;
import com.ruoyi.system.mapper.SysTextbookMapper;
import com.ruoyi.system.mapper.SysUnitMapper;
import com.ruoyi.system.mapper.SysUnitWordMapper;
import com.ruoyi.system.mapper.SysWordMapper;
import com.ruoyi.system.service.ISysWordService;

/**
 * 课程单元Service业务层处理
 * 
 * @author ruoyi
 */
@Service
public class SysWordServiceImpl implements ISysWordService 
{
	
    private static final Logger logger = LoggerFactory.getLogger(SysWordServiceImpl.class);
    
    @Autowired
    private SysTextbookMapper sysTextbookMapper;
    @Autowired
    private SysCourseMapper sysCourseMapper;
    @Autowired
    private SysWordMapper sysWordMapper;
    @Autowired
    private SysUnitMapper sysUnitMapper;
    @Autowired
    private SysUnitWordMapper sysUnitWordMapper;
    @Autowired
    private StuStudentWordMapper stuStudentWordMapper;

    /**
     * 查询单元列表
     * 
     * @param unit 单元信息
     * @return 单元集合
     */
    @Override
    public List<SysWord> selectList(SysWord unit)
    {
        return sysWordMapper.list(unit);
    }

    /**
     * @return 信息
     */
    @Override
    public SysWord selectById(Long wordId)
    {
        return sysWordMapper.selectById(wordId);
    }

    /**
     * 新增单元
     * 
     * @param unit 单元信息
     * @return 结果
     */
    @Override
    public int insert(SysWord unit)
    {
        return sysWordMapper.insert(unit);
    }

    /**
     * 修改单元
     * 
     * @param entity 信息
     * @return 结果
     */
    @Override
    public int update(SysWord entity)
    {
        return sysWordMapper.update(entity);
    }

    /**
     * 批量删除单元
     * 
     * @param wordIds 需要删除的ID
     * @return 结果
     */
    @Override
    public int deleteByIds(Long[] wordIds)
    {
    	// 删除单元-单词
    	sysUnitWordMapper.deleteByWordIds(wordIds);
    	// 删除学生-单词
    	stuStudentWordMapper.deleteByWordIds(wordIds);
        return sysWordMapper.deleteByIds(wordIds);
    }

    /**
     * 查询未分配班级的学员列表
     * 
     * @param classId 班级ID
     * @return 用户列表
     */
    @Override
    public List<SysWord> listAll()
    {
        return sysWordMapper.listAll();
    }

    /**
     * 查询未分配班级的学员列表
     * 
     * @param classId 班级ID
     * @return 用户列表
     */
    @Override
    public List<SysWord> listSelected(Long unitId)
    {
        return sysWordMapper.selectSelectedWordListByUnitId(unitId);
    }

    /**
     * 导入用户数据
     * 
     * @param dataList 数据列表
     * @param isUpdateSupport 是否更新支持，如果已存在，则进行更新数据
     * @param operName 操作用户
     * @return 结果
     */
    @Override
    public String importData(List<SysWord> dataList)
    {
    	System.out.println(JSON.toJSONString(dataList));
        if (StringUtils.isNull(dataList) || dataList.size() == 0)
        {
            throw new ServiceException("导入用户数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        
        // 处理教材
        Map<String, Long> textbookName_textbookId_MAP = new HashMap<String, Long>();
        for (SysWord entity : dataList) {
        	if (textbookName_textbookId_MAP.containsKey(entity.getTextbookName())) {
				continue;
			} else {
	        	SysTextbook sysTextbook = sysTextbookMapper.selectByTextbookName(entity.getTextbookName());
	        	if (sysTextbook == null) {
	        		sysTextbook = new SysTextbook();
	        		sysTextbook.setTextbookName(entity.getTextbookName());
	        		sysTextbookMapper.insert(sysTextbook);
				}
        		textbookName_textbookId_MAP.put(entity.getTextbookName(), sysTextbook.getTextbookId());
			}
        }
        
        // 处理课程
        Map<String, Long> courseName_courseId_MAP = new HashMap<String, Long>();
        for (SysWord entity : dataList) {
        	System.out.println("courseName---" + JSON.toJSONString(entity));
        	if (courseName_courseId_MAP.containsKey(entity.getCourseName())) {
				continue;
			} else {
	        	SysCourse sysCourse = sysCourseMapper.selectByCourseName(entity.getCourseName());
	        	if (sysCourse == null) {
	        		sysCourse = new SysCourse();
	        		sysCourse.setCourseName(entity.getCourseName());
	        		sysCourse.setTextbookId(textbookName_textbookId_MAP.get(entity.getTextbookName()));
	        		sysCourseMapper.insert(sysCourse);
				}
	        	courseName_courseId_MAP.put(entity.getCourseName(), sysCourse.getCourseId());
			}
        }
        
        // 处理单元
        Map<String, Long> unitName_unitId_MAP = new HashMap<String, Long>();
        for (SysWord entity : dataList) {
        	if (unitName_unitId_MAP.containsKey(entity.getUnitName())) {
				continue;
			} else {
	        	SysUnit sysUnit = sysUnitMapper.selectByUnitName(entity.getUnitName());
	        	if (sysUnit == null) {
	        		sysUnit = new SysUnit();
	        		sysUnit.setUnitName(entity.getUnitName());
	        		sysUnit.setCourseId(courseName_courseId_MAP.get(entity.getCourseName()));
	        		sysUnitMapper.insert(sysUnit);
				}
	        	unitName_unitId_MAP.put(entity.getUnitName(), sysUnit.getUnitId());
			}
        }
        
        for (SysWord entity : dataList) {
            try {
            	Long unitId = unitName_unitId_MAP.get(entity.getUnitName());
//                BeanValidators.validateWithException(validator, entity);
            	// 添加单词
            	SysWord sysWord = sysWordMapper.selectByWordName(entity.getWordName());
            	if(sysWord == null) {
            		sysWord = new SysWord();
            		sysWord.setWordName(entity.getWordName());
            		sysWord.setWordMeaning(entity.getWordMeaning());
            		sysWord.setWordVoiceLabel(entity.getWordVoiceLabel());
            		sysWord.setWordVoiceName(entity.getWordVoiceName());
                    sysWordMapper.insert(sysWord);
            	}
            	Long wordId = sysWord.getWordId();
            	// 添加单元-单词
            	String unitName = entity.getUnitName();
            	if (unitName != null && unitName.length() > 0) {
					if (sysUnitWordMapper.countByUnitIdAndWordId(unitId, wordId) == 0) {
						SysUnitWord sysUnitWord = new SysUnitWord();
						sysUnitWord.setUnitId(unitId);
						sysUnitWord.setWordId(wordId);
						sysUnitWordMapper.insert(sysUnitWord);
					}
				}
            	
                successNum++;
                successMsg.append("<br/>" + successNum + "、单词名称 " + entity.getWordName() + " 导入成功");
            } catch (Exception e) {
                failureNum++;
                e.printStackTrace();
//                String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败：";
//                failureMsg.append(msg + e.getMessage());
//                log.error(msg, e);
            }
        }
        if (failureNum > 0)
        {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        }
        else
        {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    /**
     * 查询部门树结构信息
     * 
     * @param dept 部门信息
     * @return 部门树信息集合
     */
    @Override
    public List<TreeSelect> selectUnitTreeList(SysUnit sysUnit)
    {
        
        // 添加顶级【全部教材】
        List<TreeSelect> listRoot = new ArrayList<TreeSelect>();
        {
        	Long id = 0L;
        	String label = "全部教材";
        	boolean disabled = false;
        	Integer lev = 0;
        	List<TreeSelect> children = getTextbookTree();
            listRoot.add(new TreeSelect(id, label, disabled, lev, children));
        }
        return listRoot;
    }
    
    public List<TreeSelect> getTextbookTree()
    {
        List<SysTextbook> listSysTextbook = sysTextbookMapper.selectList(new SysTextbook());
        List<SysCourse> listSysCourse = sysCourseMapper.list(new SysCourse());
        List<SysUnit> listSysUnit = sysUnitMapper.list(new SysUnit());
        
        // 添加教材节点列表
        List<TreeSelect> listTextbookTree = new ArrayList<TreeSelect>();
        for(SysTextbook sysTextbook : listSysTextbook) {
        	Long id = sysTextbook.getTextbookId();
        	String label = sysTextbook.getTextbookName();
        	boolean disabled = true;
        	Integer lev = 1;
        	List<TreeSelect> children = getCourseTree(sysTextbook, listSysCourse, listSysUnit);
        	listTextbookTree.add(new TreeSelect(id, label, disabled, lev, children));
        }
        return listTextbookTree;
    }
    
    public List<TreeSelect> getCourseTree(SysTextbook sysTextBook, List<SysCourse> listSysCourse, List<SysUnit> listSysUnit)
    {
        
        // 添加教材节点列表
        List<TreeSelect> listCourseTree = new ArrayList<TreeSelect>();
        for(SysCourse sysCourse : listSysCourse) {
        	if (sysCourse.getTextbookId().longValue() != sysTextBook.getTextbookId().longValue()) {
				continue;
			} else {
	        	Long id = sysCourse.getCourseId();
	        	String label = sysCourse.getCourseName();
	        	boolean disabled = true;
	        	Integer lev = 2;
	        	List<TreeSelect> children = getUnitTree(sysCourse, listSysUnit);
	        	if (children == null || children.size() == 0) {
					continue;
				}
	        	listCourseTree.add(new TreeSelect(id, label, disabled, lev, children));
			}
        }
        return listCourseTree;
    }
    
    public List<TreeSelect> getUnitTree(SysCourse sysCourse, List<SysUnit> listSysUnit)
    {
        
        // 添加教材节点列表
        List<TreeSelect> listUnitTree = new ArrayList<TreeSelect>();
        for(SysUnit sysUnit : listSysUnit) {
        	if (sysUnit.getCourseId().longValue() != sysCourse.getCourseId().longValue()) {
				continue;
			} else {
	        	Long id = sysUnit.getUnitId();
	        	String label = sysUnit.getUnitName();
	        	boolean disabled = true;
	        	Integer lev = 3;
	        	List<TreeSelect> children = null;
	        	listUnitTree.add(new TreeSelect(id, label, disabled, lev, children));
			}
        }
        return listUnitTree;
    }

	@Override
	public void convertTextToMp3(Long wordId, String text) {
        
        Map<String, String> params = new HashMap<>();
        String salt = String.valueOf(System.currentTimeMillis());
        String signStr = YouDaoKEY.APP_KEY + text + salt + YouDaoKEY.APP_SECRET;
        String sign = getDigest(signStr);

        params.put("langType", "en");
        params.put("appKey", YouDaoKEY.APP_KEY);
        params.put("q", text);
        params.put("salt", salt);
        params.put("sign", sign);

        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(YouDaoKEY.YOUDAO_URL);
        
        List<NameValuePair> paramsList = new ArrayList<>();
        Iterator<Map.Entry<String, String>> it = params.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, String> en = it.next();
            paramsList.add(new BasicNameValuePair(en.getKey(), en.getValue()));
        }

        CloseableHttpResponse httpResponse = null;
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(paramsList, "UTF-8"));
            httpResponse = httpClient.execute(httpPost);
            
            Header[] contentType = httpResponse.getHeaders("Content-Type");
            logger.info("Content-Type: " + contentType[0].getValue());

            if ("audio/mp3".equals(contentType[0].getValue())) {
                HttpEntity httpEntity = httpResponse.getEntity();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                httpResponse.getEntity().writeTo(baos);
                byte[] audioData = baos.toByteArray();
                EntityUtils.consume(httpEntity);

                if (audioData != null && audioData.length > 0) {
                	
                	binaryToBinaryFile(audioData, RuoYiConfig.getVoicePath() + "/" + text + ".mp3");
                	
                	String wordAudioUrl = RuoYiConfig.getServerUrl() + "/profile/voice/" + text + ".mp3";
                	sysWordMapper.updateWordAudioUrl(wordId, wordAudioUrl);
                	logger.info("TTS转换成功");
                } else {
                	logger.error("生成的音频数据为空");
                }
            } else {
                HttpEntity httpEntity = httpResponse.getEntity();
                String json = EntityUtils.toString(httpEntity, "UTF-8");
                EntityUtils.consume(httpEntity);
            	logger.error("TTS转换失败：" + json);
            }
        } catch (UnsupportedEncodingException e) {
			e.printStackTrace();
        	logger.error(e.getMessage());
		} catch (ParseException e) {
        	logger.error(e.getMessage());
			e.printStackTrace();
		} catch (IOException e) {
        	logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
            if (httpResponse != null) {
                try {
                    httpResponse.close();
                } catch (IOException e) {
                    logger.error("Error closing response: " + e.getMessage());
                }
            }
        }
	}

    private String getDigest(String string) {
        if (string == null) {
            return null;
        }
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        byte[] btInput = string.getBytes(StandardCharsets.UTF_8);
        try {
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            mdInst.update(btInput);
            byte[] md = mdInst.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (byte byte0 : md) {
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (NoSuchAlgorithmException e) {
            logger.error("Error generating digest: " + e.getMessage());
            return null;
        }
    }

    public static void binaryToBinaryFile(byte[] data, String outputFilePath) {
        
        try (InputStream is = new ByteArrayInputStream(data);
             FileOutputStream fos = new FileOutputStream(outputFilePath)) {
            // 复制数据从输入流到输出流
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) != -1) {
                fos.write(buffer, 0, length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void binaryStringToBinaryFile(String binaryString, String outputFilePath) {
        // 将二进制字符串转换为字节数组
        byte[] data = new BigInteger(binaryString, 2).toByteArray();
        
        try (InputStream is = new ByteArrayInputStream(data);
             FileOutputStream fos = new FileOutputStream(outputFilePath)) {
            // 复制数据从输入流到输出流
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) != -1) {
                fos.write(buffer, 0, length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}